import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { ImageFilter, ImageGray, ImageReadTool, EdgeDetection } from 'shared';
import { ImageProcessType } from '@utils/image-process/image-process-type.enum';


@Injectable({
  providedIn: 'root'
})
export class ViewerLayoutService {

  private viewers: ViewerItem[] = [];
  private source: File | null = null;
  private viewersSub = new Subject<ViewerItem[]>();
  public viewer$ = this.viewersSub.asObservable();

  constructor() {
  }

  setSource(source: File): void {
    this.source = source;
    this.viewers.forEach(item => item.setSource(source));
  }

  addViewer(type?: ImageProcessType): void {
    if (this.source) {
      const viewer = new ViewerItem({ type, source: this.source });
      this.viewers.push(viewer);
      this.viewersSub.next(this.viewers);
    }
  }

  existSource(): boolean {
    return !!this.source
  }
}

export class ViewerItem {
  public type: ImageProcessType | null = null;
  public source: File | null = null;
  public processedImageBase64 = '';
  private extension = '';
  private processing = false;

  constructor(options: ViewerOptions) {
    this.type = options.type || null;
    this.setSource(options.source);
  }

  setSource(source: File | undefined): void {
    this.source = source || null;
    if (this.source) {
      this.extension = this.source.name.split('.').pop() || '';
    }
    this.processedImageBase64 = '';
    this.processImage();
  }

  private processImage(): void {
    if (this.source && this.type) {
      // 延时处理，防止阻塞页面渲染
      setTimeout(() => {
        this.processImageNotEmpty().then(() => {
          console.log('process success');
        });
      }, 160);
    } else {
      this.processImageEmpty();
    }
  }

  private processImageEmpty(): void {

  }

  private async processImageNotEmpty(): Promise<void> {
    this.processing = true;
    const imageU8 = await ImageReadTool.transImageToUint8Array(this.source as File);
    let processedImage: Blob | null = null;
    const type = (this.source as File).type;
    switch (this.type) {
      case ImageProcessType.GRAY:
        processedImage = await ImageGray.grayscale(imageU8, this.extension, type);
        break;
      case ImageProcessType.GAUSS_LOWER_PASS_FILTER:
        processedImage = await ImageFilter.gauss_lower_pass_filter(imageU8,
          this.extension,
          (this.source as File).type,
          5,
          0.8);
        break;
      case ImageProcessType.LOWER_PASS_FILTER:
        processedImage = await ImageFilter.lower_pass_filter(imageU8, this.extension, type, 5);
        break;
      case ImageProcessType.EDGE_DETECTION_SOBEL:
        processedImage = await EdgeDetection.sobel(imageU8, this.extension, type, 80);
        break;
    }
    if (processedImage) {
      this.processedImageBase64 = await ImageReadTool.transBlobToUrl(processedImage);
    }
    this.processing = false;
  }

}

export interface ViewerOptions {
  type?: ImageProcessType;
  source?: File;
}
